/**
 * @author roua_troua
 */
package q10.Visitor;

import q10.Arbori.Nod;
import q10.Functii.FunctiiElementare.Constanta;
import q10.Functii.FunctiiElementare.Necunoscuta;
import q10.Functii.FunctiiElementare.Putere;
import q10.Functii.FunctiiTrigonometrice.*;
import q10.Operatori.*;

public class DerivareCalculVisitor extends Visitor{
	protected String rezultat;
	protected double calculDer;
	protected CalculVisitor cv= new CalculVisitor();
	
	/**
	 * Constructorul
	 */
	public DerivareCalculVisitor(){
		this.calculDer=0;	
	}
	
	/**
	 * Constructorul
	 * @param c
	 */
	public DerivareCalculVisitor(double c){
		this.calculDer = c;	
	}
	
	/**
	 * getRezultat
	 * @return String
	 */
	public String getRezultat(){
		return rezultat;
	}
	
	/**
	 * setRezultat
	 * @param r
	 */
	public void setRezultat(String r){
		this.rezultat = r;
	}	
	
	/**
	 * getCalcul
	 * @return double
	 */
	public double getCalcul() {
		return calculDer;
	}

	/**
	 * setCalcul
	 * @param calculDer
	 */
	public void setCalcul(double calculDer) {
		this.calculDer = calculDer;
	}

	/**
	 * visit Constanta
	 * @param Constanta
	 * @return
	 */
	public void visit (Constanta cons)
	{
		this.calculDer = 0;
	}

	/**
	 * visit necunoscuta
	 * @param Necunoscuta
	 * @return
	 */
	public void visit (Necunoscuta nec)
	{
		this.calculDer=1;
	}

	/**
	 * visit sinus
	 * @param Sin
	 * @return
	 */
	public void visit(Sin s){
		if(s.getfStang()!=null){
				visit(s.getfStang());
				double fsd=this.calculDer;
				s.getfStang().acceptVisitor(cv);
				double fs=cv.getCalcul();
				this.calculDer=(Math.cos(fs))*fsd;
		}
	}
	
	/**
	 * visit cosinus
	 * @param Cos
	 * @return
	 */
	public void visit(Cos c){
		if(c.getfStang()!=null){
			visit(c.getfStang());
			double fsd=this.calculDer;
			c.getfStang().acceptVisitor(cv);
			double fs=cv.getCalcul();
			this.calculDer=(-1)*(Math.sin(fs))*fsd;		
		}
	}
	
	/**
	 * visit cat
	 * @param Cat
	 * @return 
	 */
	public void visit(Cat c) {
		if((c.getfStang()!=null)&&(c.getfDrept()!=null)){
			visit(c.getfStang());
			double fsd=this.calculDer;
			visit(c.getfDrept());
			double fdd=this.calculDer;
			
			c.getfStang().acceptVisitor(cv);
			double fs=cv.getCalcul();
			c.getfDrept().acceptVisitor(cv);
			double fd=cv.getCalcul();
			
			this.calculDer=(fsd*fd-fs*fdd)/Math.pow(fd,2);		
		}		
	}

	/**
	 * visit minus
	 * @param Minus
	 * @return
	 */
	public void visit(Minus m) {
		if((m.getfStang()!=null)&&(m.getfDrept()!=null)){
			visit(m.getfStang());
			double fsd=this.calculDer;
			visit(m.getfDrept());
			double fdd=this.calculDer;
			this.calculDer= fsd - fdd;		
		}
	}

	/**
	 * visit plus
	 * @param Plus
	 * @return
	 */
	public void visit(Plus p) {
		if((p.getfStang()!=null)&&(p.getfDrept()!=null)){
			visit(p.getfStang());
			double fsd=this.calculDer;
			visit(p.getfDrept());
			double fdd=this.calculDer;
			this.calculDer=fsd+fdd;
		}
	}

	/**
	 * visit produs
	 * @param Produs
	 * @return
	 */
	public void visit(Produs p) {
		if((p.getfStang()!=null)&&(p.getfDrept()!=null)){
			visit(p.getfStang());
			double fsd=this.calculDer;
			visit(p.getfDrept());
			double fdd=this.calculDer;
			
			p.getfStang().acceptVisitor(cv);
			double fs=cv.getCalcul();
			p.getfDrept().acceptVisitor(cv);
			double fd=cv.getCalcul();
			
			this.calculDer=fsd*fd + fs*fdd;		
		}
	}

	/**
	 * visit putere
	 * @param Putere
	 * @return
	 */
	public void visit(Putere p) {
		if((p.getfStang() != null)&&(p.getfDrept() != null)){
			visit(p.getfStang());
			double fsd=this.calculDer;			
			
			p.getfStang().acceptVisitor(cv);
			double fs=cv.getCalcul();
			p.getfDrept().acceptVisitor(cv);
			double fd=cv.getCalcul();
			
			this.calculDer=fd*Math.pow(fs, fd-1)*fsd;
		
		}
	}

	/**
	 * Neimplementata
	 */
	public void visit(Tg tg){
		
	}
	
	/**
	 * Neimplementata
	 */
	public void visit(Ctg ctg){
		
	}


	/**
	 * visit Nod
	 * @param Nod
	 * @return
	 */
	public void visit(Nod n) {
		if(n instanceof Plus)
			visit((Plus)n);
			else if (n instanceof Constanta)
				visit((Constanta)n);
				else if (n instanceof Necunoscuta)
					visit((Necunoscuta)n);
					else if (n instanceof Minus)
						visit((Minus)n);
						else if (n instanceof Cat)
							visit((Cat)n);
							else if (n instanceof Plus)
								visit((Plus)n);
								else if (n instanceof Produs)
									visit((Produs)n);
									else if (n instanceof Putere)
										visit((Putere)n);
										else if (n instanceof Cos)
											visit((Cos)n);											
	}
}
